import javavatask.storage as st

class AbstractModel(object):
    """Basic interface for the task model"""

    def __init__(self):
        self.listeners = []

    def addListener(self, listenerFunc):
        self.listeners.append(listenerFunc)

    def removeListener(self, listenerFunc):
        self.listeners.remove(listenerFunc)

    def update(self):
        for eachFunc in self.listeners:
            eachFunc(self)

class Task(object):
    """Define the attributes of one task in this class. The following is the 
    attributes:
    
    id - The unique identifier of the task.
    date - The date when it is created or finished, subject to the status.
    label - The description of the task.
    status - This attribute indicates the current status of the task, it 
             is a string that includes three figures:
             1. The first figure means whether this task is finished or not,
                1 - in progress, 0 - finished.
             2. The second figure means the importance, it could be 1..5, 
                the larger this figure is, the more important this task will
                be.
             3. The third figure indicates the urgent level of this task, it
                should be 1..5, the larger this figure is, the higher urgent
                level this task will be.
             
             For example, if status='025', it means the task is in progress, 
             and the importance value is 2, and the urgent level is 5, so it 
             is very urgent.
    
    This object will be held by TaskListModel.
    """
    
    def __init__(self, id, date, label, status='111'):
        self.id = id
        self.date = date
        self.label = label
        self.status = status
    
    def __str__(self):
        attTuple = (self.id, self.date, self.label, self.status)
        return str(attTuple)

class TaskListModel(AbstractModel):
    """The model for task list, this class supports several methods to 
    manipulate the task data.
    """
    
    def __init__(self, taskList=None):
        AbstractModel.__init__(self)
        
        if taskList:
            self.taskList = taskList
        else:
            self.taskList = self.load()
        self.__sort()

    def addTask(self, task):
        "Add a task to the model."
        
        self.taskList.append(task)
        self.__sort()
        self.save()
        self.update()
    
    def setTaskStatus(self, index, status):
        "Set new status for a task in place by specific index."
        
        self.taskList[index].status = status
        self.save()
        self.update()

    def setTaskLabel(self, index, label):
        "Set new label for a task in place by specific index."
        self.taskList[index].label = label
        self.save()
        self.update()
    
    def deleteTask(self, index):
        "Delete a task from the model."
        del self.taskList[index]
        self.save()
        self.update()
    
    def __sort(self):
        self.taskList.sort(key=(lambda x: x.status), reverse=True)

    def sortTasks(self):        
        "Sort the task list by status code reversely."
        self.__sort()
        self.update()
    
    def getSize(self):
        return len(self.taskList)
    
    def getTask(self, index):
        return self.taskList[index]
    
    def load(self):
        # Load data of tasks from file.
        loaded = st.loadTasks(None)
        inProgressTasks = stringToTasks(loaded[0])
        finishedTasks = stringToTasks(loaded[1])

        return inProgressTasks + finishedTasks
    
    def save(self):
        inProgressTasks = []
        finishedTasks = []
        for task in self.taskList:
            if task.status[0] == '1':
                inProgressTasks.append(task)
            else:
                finishedTasks.append(task)
        
        string1 = tasksToString(inProgressTasks)
        string2 = tasksToString(finishedTasks)
        st.saveTasks(None, string1, string2)

def tasksToString(tasks):
    strings = []
    for task in tasks:
        strings.append(str(task))
    return str(strings)

def stringToTasks(string):
    tasks = []

    if not string:
        return tasks

    strlist = eval(string)
    
    for s in strlist:
        attTuple = eval(s)
        task = Task(*attTuple)
        tasks.append(task)

    return tasks

if __name__ == '__main__':
    # Do some test here.

    id = 100
    status = '011'
    newTask = Task(id, '20080804', 'New task', status)
    print str(newTask)
